#pragma once
#include <pthread.h>
#include <vector>
#include <queue>
#include <string>
#include <functional>

template <typename T>
class ThreadPool
{
public:
    //同步与互斥接口
    void LockQueue(pthread_mutex_t &mutex)//加锁
    {
        int n = pthread_mutex_lock(&_mutex);
        if(n)
        {
            printf("Lock Error!\n");
            return;
        }
    }
    void UnlockQueue(pthread_mutex_t &mutex)//解锁
    {
        int n = pthread_mutex_unlock(&_mutex);
        if(n)
        {
            printf("Unlock Error!\n");
            return;
        }
    }
    void ThreadSleep(pthread_cond_t &cond)//使线程进入条件变量中等待
    {
        ++_waitnum;
        pthread_cond_wait(&_cond,&_mutex);
        --_waitnum;
    }
    void WakeupAllThread(pthread_cond_t &cond)//唤醒所有条件变量的接口
    {
        pthread_cond_broadcast(&_cond);
    }

    //默认成员函数
    ThreadPool(int num = 3):_threadnum(num),_is_running(true),_waitnum(0)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }
    ThreadPool(const ThreadPool &tp) = delete;
    ThreadPool &operator=(const ThreadPool &tp) = delete;
public:
    //单例相关
    static ThreadPool<T> *GetInstance();//获取/创建单例对象

    //控制线程池
    void WaitAll()//等待线程池中所有线程
    {
        for(auto thread : _threads)
        {
            thread.Join();
        }
    }
    void HandlerTask()//用于线程处理任务队列中的任务
    {
        while(true)
        {
            LockQueue(_mutex);
            while(_task_queue.empty() && _is_running) ThreadSleep(_cond);
            if(_task_queue.empty() && !_is_running)
            {
                UnlockQueue(_mutex);
                break;
            }

            T t = _task_queue.front();
            _task_queue.pop();
            UnlockQueue(_mutex);
            t();
        }
    }
    void Enqueue(T t)//主线程向任务队列中发任务的接口
    {
        LockQueue(_mutex);
        if(_is_running)
        {
            _task_queue.push(t);
        }
        if(_waitnum > 0) WakeupAllThread(_cond);
        UnlockQueue(_mutex);
    }

    void Start()//启动线程池
    {
        for(int i = 0 ; i < _threadnum ; ++i)
        {
            auto func = std::bind(&ThreadPool::HandlerTask,this);
            std::string thread_name = "Thread-" + std::to_string(i);
            _threads.emplace_back(thread_name,func);
        }
        for(int i = 0 ; i < _threadnum ; ++i)
        {
            _threads[i].Start();
        }
    }
    void Exit()//线程池退出
    {
        _is_running = false;
        WakeupAllThread(_cond);
    }

protected:
    //线程池相关
    int _threadnum;//线程数量，固定！
    std::vector<Thread> _threads;//管理线程池中的线程
    std::queue<T> _task_queue;//任务队列(共享资源)
    pthread_mutex_t _mutex;//保护任务队列的互斥锁
    pthread_cond_t _cond;//保护任务队列的条件变量
    bool _is_running;//线程池是否正在运行的标识符


    // 优化相关
    int _waitnum;//记录条件变量下等待的线程个数，防止无效唤醒
    

    // 单例对象相关
    static ThreadPool<T> *_instance;//懒汉模式，单例对象
    static pthread_mutex_t _lock;
};
template <typename T>
ThreadPool<T> * ThreadPool<T>::_instance = nullptr;

template <typename T>
pthread_mutex_t ThreadPool<T>::_lock = PTHREAD_MUTEX_INITIALIZER;